using System;
using System.Linq;
using System.Runtime.InteropServices;
using RayDen.Library.Core;

namespace RayDen.Library.Components.PhotonMapping
{
    using RayDen.Library.Core.Primitives;

    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public struct Photon : ISerializableValue {
        public Point Position;
        public RgbSpectrum Power;
        public byte Phi, Theta, Plane;


        public Photon(ref Point pt, ref Vector dir, ref RgbSpectrum power)
        {
            var dirx = MathLab.Clamp(dir.z, -1f, 1f);

            int theta = Convert.ToInt32(Math.Acos(dirx) * (256.0d / Math.PI));
            if (theta > 255)
                theta = 255;

            Theta = (byte)theta;

            int phi = Convert.ToInt32(Math.Atan2(dir.y, dir.x) * (256.0d / 2.0 * Math.PI));


            if (phi > 255)
                phi = 255;
            else

                if (phi < 0)
                    phi = phi + 256;

            Phi = (byte)phi;
            Position = pt;
            Power = power;
            Plane = 0;
        }
        //public Vector Direction;

        public void SetPower(RgbSpectrum rgbSpectrum) {
            this.Power = rgbSpectrum;
        }

        internal void SetPlane(byte axis) {
            this.Plane = axis;
        }

        internal void ScalePower(float scale)
        {
            this.Power /= scale;
        }

        public byte[] Serialize()
        {
            return new[]
                {
                    Position.Serialize(),
                    Power.Serialize(),
                    new [] {Phi, Theta, Plane}
                    
                }.SelectMany(t => t).ToArray();
        }

        public void Deserialize(byte[] data, int offset = 0)
        {
            Position.Deserialize(data, offset);
            Power.Deserialize(data, offset + 12);
            Phi = data[offset + 24];
            Theta = data[offset + 25];
            Plane = data[offset + 26];
        }
    }
}